package learn.up.collections;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.junit.Test;

/**
 *
 * @author NANUTO
 * @date 2017年12月5日 上午12:11:56
 */
public class ListDemo {

	@Test
	public void test1() {
		List<Integer> list = new ArrayList<>();
		Collections.addAll(list, 1, 2, 3, 5, 6);

		// for循环优化写法，只获取一次长度
		/*
		 * for (int i = 0, size = list.size(); i < size; i ++) { Integer integer =
		 * list.get(i); if (integer == 3 || integer == 5) list.remove(integer); }
		 */
		/**
		 * 执行后，会抛出IndexOutOfBoundsException，因为集合中存在符合条件的元素，
		 * 删除后，集合长度动态改变，由于长度只获取一次，发生越界,所以，去掉for循环优化
		 */
		for (int i = 0; i < list.size(); i++) {
			Integer integer = list.get(i);
			if (integer == 3 || integer == 5)
				list.remove(integer);
		}
		/**
		 * 执行后，输出：[1, 2, 5, 6]，漏掉了5这个元素，当i=2的时候，值为3，删除后，后面的
		 * 元素往前补一位，这时i=3的时候，值为6，跳过了5，这样也不行，随后想到了用for循 
		 * 环增强，不显示的操作下标，直接操作对象，如：
		 */
		for (Integer value : list) {
			// 符合条件，删除元素
			if (value == 3 || value == 5) {
				list.remove(value);
			}
		} 
		/**
		 * 执行后，会抛出ConcurrentModificationException，字面意思是并发修改异常。异常跟踪信息如下：
		 * 而要解决这个问题，可以使用Iterator的remove方法，该方法会删除当前迭代对象的同时，维护索引的一致性。
		 */
		  Iterator<Integer> it = list.iterator();  
	       while(it.hasNext()) {  
	           Integer value = it.next();  
	           if(value == 3 || value == 5) {  
	              it.remove();  
	           }  
	       }  
	       /**
	        * 不使用迭代器的解决方案就是，自己维护索引，删除一个元素后，索引-1，如：
	        */
	       for (int i = 0; i < list.size(); i ++) {
	    		Integer integer = list.get(i);
				if (integer == 3 || integer == 5) {
					list.remove(integer);
					i --;
				}
	       }
	       /**
	        * 还有种取巧的方式是从最后一个元素开始遍历，符合条件的删除
	        */
	       for (int i = list.size() - 1; i >= 0; i --) {
	    		Integer integer = list.get(i);
				if (integer == 3 || integer == 5) {
					list.remove(integer);
				}
	       }
	}
}
